import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
import AlipaySDK from 'alipay-sdk';
import { Logger } from '@/utils/log4js';
import { pemMap } from '@/pem2';
import * as sd from 'silly-datetime';
import { InjectModel } from '@nestjs/sequelize';
import { Orders } from '@/models/orders.model';
import { VipTypes } from '@/models/vipTypes.model';
import { UserVips } from '@/models/userVips.model';
import { REQUEST } from '@nestjs/core';
import random from 'string-random';
import { Sequelize } from 'sequelize-typescript';
@Injectable()
export class PaymentService {
  constructor(
    @InjectModel(Orders)
    private readonly orders: typeof Orders,

    @InjectModel(VipTypes)
    private readonly vipTypes: typeof VipTypes,

    @InjectModel(UserVips)
    private readonly userVips: typeof UserVips,

    @Inject(REQUEST)
    private readonly request: Request & { user: { userId: number } },

    private sequelize: Sequelize,
  ) {}

  async getVipTypes() {
    return await this.vipTypes.findAll({
      attributes: { exclude: ['created_time', 'updated_time'] },
      where: { status: 1 },
    });
  }
  async pay(params): Promise<any> {
    const { id } = params;
    const t = await this.sequelize.transaction();
    try {
      const orderNum =
        sd.format(new Date(), 'YYYYMMDDHHmm') +
        '' +
        random(6, { numbers: true, letters: false });
      const vipInfo = await this.vipTypes.findOne({
        attributes: { exclude: ['created_time', 'updated_time'] },
        where: {
          id,
        },
      });

      await this.orders.create(
        {
          orderNum: orderNum,
          amount: vipInfo.price,
          vipType: vipInfo.id,
          status: 0,
          paymentMethod: 'alipay',
          desc: vipInfo.name,
          userId: this.request.user.userId,
        },
        {
          transaction: t,
        },
      );

      const alipaySdk = new AlipaySDK({
        appId: '2021004145616071', // 你自己的沙箱黄环境的appId
        privateKey: pemMap.app_private_key,
        alipayPublicKey: pemMap.alipay_public_key,
        gateway: 'https://openapi.alipay.com/gateway.do',
      });

      const bizContent = {
        out_trade_no: orderNum,
        qr_pay_mode: 4,
        product_code: 'FAST_INSTANT_TRADE_PAY',
        subject: vipInfo.name,
        body: vipInfo.name,
        total_amount: vipInfo.price,
      };

      // 支付页面接口，返回 html 代码片段，内容为 Form 表单
      const result = alipaySdk.pageExec('alipay.trade.page.pay', {
        method: 'GET',
        bizContent,
        // returnUrl: 'https://www.jianli101.com',
        notifyUrl: 'https://www.jianli101.com/api/alipay/payCallback',
      });
      await t.commit();
      return result;
    } catch (error) {
      await t.rollback();
      throw new HttpException(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }
  async payCallback(params): Promise<any> {
    Logger.access('payCallback' + JSON.stringify(params, null, 2));
    await this.updatePayStatus(params);
  }
  async updatePayStatus(params) {
    const { out_trade_no, trade_no } = params;
    await this.orders.update(
      {
        status: 1,
        tradeNo: trade_no,
      },
      {
        where: {
          orderNum: out_trade_no,
        },
      },
    );
    const order = await this.orders.findOne({
      where: {
        orderNum: out_trade_no,
      },
    });
    if (order && order.vipType) {
      try {
        const result = await this.userVips.update(
          {
            vipTypeId: order.vipType,
            purchaseDate: sd.format(new Date(), 'YYYY-MM-DD HH:mm:ss'),
          },
          {
            where: {
              userId: this.request.user.userId,
            },
          },
        );
        if (result && result[0] && result[0] == 1) {
        } else {
          await this.userVips.create({
            userId: this.request.user.userId,
            vipTypeId: order.vipType,
            purchaseDate: sd.format(new Date(), 'YYYY-MM-DD HH:mm:ss'),
          });
        }
      } catch (e) {}
    }
  }
  async getVipInfo(): Promise<any> {
    if (this.request.user?.userId) {
      const vipInfo = await this.userVips.findOne({
        attributes: { exclude: ['created_time', 'updated_time'] },
        where: {
          userId: this.request.user?.userId,
        },
      });
      const result = vipInfo?.dataValues || null;
      try {
        if (vipInfo && vipInfo.isActive) {
          const vipType = await this.vipTypes.findOne({
            where: {
              id: vipInfo.vipTypeId,
            },
          });
          if (!vipType.durationDays && vipType.limitTimes) {
            if (
              vipInfo.downloadTimes &&
              vipInfo.downloadTimes >= +vipType.limitTimes
            ) {
              await this.userVips.update(
                {
                  isActive: 0,
                },
                {
                  where: {
                    id: vipInfo.id,
                  },
                },
              );
              result.isActive = 0;
            }
          }
          if (vipType.durationDays && !vipType.limitTimes) {
            if (
              Date.now() - new Date(vipInfo.purchaseDate).getTime() >=
              vipType.durationDays * 24 * 3600 * 1000
            ) {
              await this.userVips.update(
                {
                  isActive: 0,
                },
                {
                  where: {
                    id: vipInfo.id,
                  },
                },
              );
              result.isActive = 0;
            }
          }
        }
      } catch (e) {}

      return result;
    }
    return null;
    // return await this.userVips.findOne({
    //   attributes: { exclude: ['created_time', 'updated_time'] },
    //   where: {
    //     userId: this.request.user?.userId,
    //     isActive: 1,
    //   },
    //   order: [['id', 'desc']],
    // });
  }
}
